package fatworm.query.expression;

import fatworm.query.Plan;
import fatworm.query.Scan;
import fatworm.storage.table.Schema;
import fatworm.util.*;

public class OpAllTerm implements Term {
	
	private Expression lexp, rexp;
	private int opcode;
	
	public OpAllTerm(Expression lexp, Expression rexp, int opcode) {
		this.lexp = lexp;
		this.rexp = rexp;
		this.opcode = opcode;
	}
	
	private boolean isFit(int x) {
		switch (opcode) {
		case Const.EQ: 
			return x == 0;
		case Const.GT:
			return x > 0;
		case Const.LT:
			return x < 0;
		case Const.GE:
			return x <= 0;
		case Const.LE:
			return x >= 0;
		case Const.NE:
			return x != 0;
		default:
			Lib.assertNotReached();
			return false;
		}
	}
	
	public boolean isOK(Scan s) {
		Plan p = rexp.asSubquery();
		Scan subs = p.open();
		String name = null;
		for (String str : p.getSchema().fields())
			name = str;
		
		while (subs.next())
			if (!isFit(lexp.evaluate(s).compareTo(subs.getVal(name))))
				return false;
		
		return true;
	}
	
	public boolean isIn(Schema sch) {
		return lexp.isIn(sch) && rexp.isIn(sch);
	}
	
	public int reductionFactor(Plan p) {
		return 1;
	}
	
	public String toString() {
		String op = "";
		
		switch (opcode) {
		case Const.EQ: 
			op = "=";
			break;
		case Const.GT:
			op = ">";
			break;
		case Const.LT:
			op = "<";
			break;
		case Const.GE:
			op = ">=";
			break;
		case Const.LE:
			op = "<=";
			break;
		case Const.NE:
			op = "<>";
			break;
		default:
			Lib.assertNotReached();
		}
		
		return lexp.toString() + op + " ALL " + rexp.toString();
	}
}